/* eslint-disable camelcase */
const { Service } = require('egg')
const cheerio = require('cheerio')
const { MD5, Base64 } = require('../utils/encryption')
const { strEnc } = require('../utils/DES')

/**
 * * 检查密码是否符合规则
 * @param {*} sid *
 * @param {*} pwd *
 * @return { object }*
 */
function checkpwd(sid, pwd) {
  function charType(num) { // 内部函数，用于判断字符类型
    // 数字字符
    if (num >= 48 && num <= 57) { return 8 }
    // 小写字母字符
    if (num >= 97 && num <= 122) { return 4 }
    // 大写字母字符
    if (num >= 65 && num <= 90) { return 2 }
    // 其他字符
    return 1
  }

  // 初始化结果
  let result = 0
  // 遍历密码中的每个字符，计算字符类型的结果
  for (let i = 0, len = pwd.length; i < len; ++i) { result |= charType(pwd.charCodeAt(i)) }
  // 密码规则 = 结果
  const txt_mm_expression = result
  // 密码长度
  const txt_mm_length = pwd.length
  // 判断密码中是否包含sid
  const txt_mm_userzh = pwd.toLowerCase().trim().indexOf(sid.toLowerCase().trim()) > -1 ? '1' : '0'
  // 返回结果对象
  return { txt_mm_expression, txt_mm_length, txt_mm_userzh }
}

/**
 * * 检测密码是否合法
 * @param {*} sid *
 * @param {*} pwd *
 * @return { string } *
 */
function isPasswordPolicy(sid, pwd) {
  // 检查密码是否为空或用户名和密码是否相同
  if (pwd === '' || pwd == null || sid === pwd) {
    return '0'
  }
  const passwordlen = pwd.length
  // 检查密码长度是否小于6位
  if (passwordlen < 6) {
    return '0'
  }
  return '1'
}

module.exports = class LoginService extends Service {
  /**
   * * 模拟登录，获取cookie
   * @return {setCookie: string, status: number} **
   */
  async getCookie() {
    try {
      const { ctx } = this
      const { sid, pwd } = ctx.data

      /* * 0.计算所需使用的一些加密参数 */
      const randnumber = ''
      const passwordPolicy = isPasswordPolicy(sid, pwd)
      const { txt_mm_expression, txt_mm_length, txt_mm_userzh } = checkpwd(sid, pwd)
      const hid_flag = '1'
      const p_username = `_u${randnumber}`
      const p_password = `_p${randnumber}`
      // console.log('randnumber', randnumber);
      // console.log('passwordPolicy', passwordPolicy);
      // console.log('txt_mm_expression', txt_mm_expression);
      // console.log('txt_mm_length', txt_mm_length);
      // console.log('txt_mm_userzh', txt_mm_userzh);
      // console.log('hid_flag', hid_flag);
      // console.log('p_username', p_username);
      // console.log('p_password', p_password);
      /* end */

      /* * 1.请求主页，获取包含加密参数的js文件地址，并记录cookie用于后续请求 */
      const homeUrl = `${ctx.state.baseUrl}/cssfjw/cas/login.action`
      const homeRes = await ctx.curl(homeUrl, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
        },
      })
      const temCookie = homeRes.headers['set-cookie'] ? homeRes.headers['set-cookie'].map((e) => e.split(';')[0]).join(';') : ''
      const $ = cheerio.load(homeRes.data.toString())
      const js_SetKingoEncypt = `${ctx.state.baseUrl}${$('#kingo_encypt').attr().src}` // 记录了加密所需参数的js文件地址
      /* end */

      /* * 2.请求js文件，获取加密所需参数 */
      const jsRes1 = await ctx.curl(js_SetKingoEncypt, {
        method: 'GET',
        headers: {
          Cookie: temCookie,
          'Content-Type': 'application/x-www-form-urlencoded',
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
        },
      })
      // console.log(jsRes1.data.toString().trim().split(';').slice(0, 3));
      const encryptionParameter = jsRes1.data.toString().trim().split(';').slice(0, 3).map((e) => {
        const line = e.split('=')
        return { [line[0].replace('var', '').replace(/\s/g, '').replace(/'/g, '')]: line[1].trim().replace(/'/g, '') }
      }) // 对字符串形式的js代码进行切割，获取所需加密参数
      // console.log('encryptionParameter', encryptionParameter);
      const _deskey = encryptionParameter[0]._deskey
      const _nowtime = encryptionParameter[1]._nowtime
      const _ssessionid = encryptionParameter[2]._ssessionid
      // console.log('encryptionParameter', encryptionParameter);
      /* end */

      /* * 3.开始构造加密所需参数 */
      const password = MD5(MD5(pwd) + MD5(''))
      const username = Base64(`${sid};;${_ssessionid}`)
      let params = `${p_username}=${username}&${p_password}=${password}&randnumber=${randnumber}&isPasswordPolicy=${passwordPolicy
      }&txt_mm_expression=${txt_mm_expression}&txt_mm_length=${txt_mm_length}&txt_mm_userzh=${txt_mm_userzh}&hid_flag=${hid_flag}&hidlag=1`
      const token = MD5(MD5(params) + MD5(_nowtime))
      params = Base64(strEnc(params, _deskey, null, null)) // 对params进行DES加密，后进行Base64编码
      // console.log('password', password);
      // console.log('username', username);
      // console.log('params', params);
      // console.log('token', token);

      /* * 4.登录 */
      const logingUrl = `${ctx.state.baseUrl}/cssfjw/cas/logon.action`
      const loginRes = await ctx.curl(logingUrl, {
        method: 'POST',
        headers: {
          Cookie: temCookie,
          'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
        },
        data: {
          params,
          token,
          timestamp: _nowtime,
          deskey: _deskey,
          ssessionid: _ssessionid,
        },
      })
      const data = JSON.parse(loginRes.data.toString())
      // console.log('data', data);

      if (data.status === '200') {
        const setCookie = loginRes.headers['set-cookie'] ? loginRes.headers['set-cookie'].map((e) => e.split(';')[0]).join(';') : ''
        return { setCookie, status: 302 }
      }
      if (data.status === '402') {
        return { setCookie: '', status: 200 }
      }
      return { setCookie: '', status: data.status }
    } catch (err) {
      console.log(err)
      return { setCookie: '', status: 500 }
    }
  }
}
